/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package structures.grammar;

import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import structures.table.symboltable.GlobalItemInfoTable;
import structures.table.symboltable.ItemInfo;
import bangor.aiia.jge.bnf.BNFGrammar;
import bangor.aiia.jge.bnf.BNFProduction;
import bangor.aiia.jge.bnf.BNFRule;
import bangor.aiia.jge.bnf.BNFSymbol;

/**
 *
 * @author vlad
 */
public class BNFGrammarReader implements GrammarReader {

    private GlobalItemInfoTable table;

    public BNFGrammarReader(GlobalItemInfoTable table) {
        this.table = table;
    }

    @Override
    public Grammar parse(String grammar) {
        // XStream xstream = new XStream(new DomDriver());
        BNFGrammar BNFGrammar = new BNFGrammar(grammar);
        LinkedList<String> usedSymbols = new LinkedList<String>();
        Queue<BNFSymbol> queue = new LinkedList<BNFSymbol>();
        List<Rule> rules = new LinkedList<Rule>();
        BNFSymbol curSymbol = BNFGrammar.getStartSymbol();
        BNFRule curRule;
        int i;
        int count = 0;
        queue.add(curSymbol);
        usedSymbols.add(curSymbol.getValue().trim());

        while (!queue.isEmpty()) {
            curSymbol = queue.remove();
            curRule = BNFGrammar.getRule(curSymbol);
            if (curRule == null) {
                continue;
            }
            ItemInfo from = table.addGrammarItem(curRule.getHead().getValue().trim(),
                    !curRule.getHead().isTerminal());

            for (BNFProduction p : curRule.getProductions()) {
                count = 0;
                for (BNFSymbol sym : p.getSymbols()) {
                    if (!sym.getValue().trim().isEmpty()) {
                        count++;
                    }
                }
                if (count > 0) {
                    //System.out.println("\nfrom = " + from);
                }
                ItemInfo[] to = new ItemInfo[count];
                i = 0;
                for (BNFSymbol sym : p.getSymbols()) {
                    String val = sym.getValue().trim();
                    if (!val.isEmpty()) {
                        to[i] = table.addGrammarItem(sym.getValue().trim(), !sym.isTerminal());
                        //System.out.println("Sym = " + val);
                        //System.out.println("to[" + i + "] =" + to[i]);
                        if (!usedSymbols.contains(val) && !sym.isTerminal()) {
                            //System.out.println("Added to stack = " + val);
                            queue.add(sym);
                            usedSymbols.add(val);
                        }
                        i++;
                    }
                }
                if (count > 0) {
                    //System.out.println("from = " + from);
                    rules.add(new Rule(from, new ItemList(to)));
                }
            }

        }

        Grammar res = new Grammar();
        for (Rule rl : rules) {
            res.put(rl);
        }
        // System.out.println(xstream.toXML(rules));
        return res;

    }
}
